package org.darcy.config;


import javax.sql.DataSource;

import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;

import lombok.extern.slf4j.Slf4j;

/**
 * mybatis plus config
 */
@Configuration
@Slf4j
@MapperScan(basePackages = "org.darcy.dao")
@Order(1)
public class MybatisConfig {
	
	@Bean("defaultDataSource")
	@ConfigurationProperties("spring.datasource")
	public DataSource dataSource() {
		log.info("step1：定义数据源");
		return DruidDataSourceBuilder.create().build();
	}

	@Bean(name = "mybatisConfiguration")
	public MybatisConfiguration config() throws Exception {
		log.info("step2：定义MybatisConfiguration");
		MybatisConfiguration configuration = new MybatisConfiguration();
		configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
		configuration.setJdbcTypeForNull(JdbcType.NULL);
		return configuration;

	}

	/**
	 * mybatis plus 单数据源不需要配置SqlSessionFactory，因为重新写了MybatisSqlSessionFactoryBean。
	 * 多数据源则必须配置，不然mapper无法绑定，此时需要注意，分页插件需要手动加入到SqlSessionFactory的配置中
	 */
	@Primary
	@Bean(name = "defaultSqlSessionFactory")
	@DependsOn(value = "defaultDataSource")
	public MybatisSqlSessionFactoryBean defaultSqlSessionFactory(@Qualifier("defaultDataSource") DataSource dataSource,
			@Qualifier("pageInterceptor") MybatisPlusInterceptor pageInterceptor,
			@Qualifier("mybatisConfiguration") MybatisConfiguration mybatisConfiguration) throws Exception {
		log.info("step3：定义SqlSessionFactory");
		MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();

		PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
		sqlSessionFactory.setMapperLocations(resolver.getResources("mybatis/mapper/**/*.xml"));

		sqlSessionFactory.setDataSource(dataSource);
		sqlSessionFactory.setTypeAliasesPackage("org.darcy.model.*");
		sqlSessionFactory.setConfiguration(mybatisConfiguration);
		// 下面这句不加，则分页插件无法正常使用
		sqlSessionFactory.setPlugins(pageInterceptor);
		sqlSessionFactory.setTransactionFactory(new SpringManagedTransactionFactory());
		return sqlSessionFactory;
	}

	@Bean(name = "pageInterceptor")
	public MybatisPlusInterceptor mybatisPlusInterceptor() {
		log.info("Mybatis Plus 分页插件");
		MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
		interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
		return interceptor;
	}

	@Bean("transactionManager")
	public DataSourceTransactionManager getDataSourceTransactionManager(
			@Qualifier("defaultDataSource") DataSource dataSource) {
		log.info("step4：定义事务管理器transactionManager");
		DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
		transactionManager.setDataSource(dataSource);
		return transactionManager;
	}
	
}
